package com.bskj.kuaifu.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.util.DateUtil;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bskj.common.bean.model.ParkingLotCustomer;
import com.bskj.common.bean.model.ParkingShop;
import com.bskj.common.bean.model.ShopCoupon;
import com.bskj.common.bean.model.ThirdPlatformInterface;
import com.bskj.common.bean.model.UserCar;
import com.bskj.common.bean.model.UserCoupon;
import com.bskj.common.bean.model.UserInfo;
import com.bskj.common.dao.ParkingLotCustomerDao;
import com.bskj.common.dao.ParkingShopDao;
import com.bskj.common.dao.ShopCouponDao;
import com.bskj.common.dao.ThirdPlatformInterfaceDao;
import com.bskj.common.dao.UserCarDao;
import com.bskj.common.dao.UserCouponDao;
import com.bskj.common.dao.core.BaseDao;
import com.bskj.common.dao.core.FindRequestEntity;
import com.bskj.common.dao.core.OrderEnum;
import com.bskj.common.dao.core.WhereEnum;
import com.bskj.common.enums.CouponLimitModeTypeEnum;
import com.bskj.common.enums.CouponStatusEnum;
import com.bskj.common.enums.CouponTimeTypeEnum;
import com.bskj.common.enums.ShopCouponValidTypeEnum;
import com.bskj.common.enums.SweepCodeEnum;
import com.bskj.common.enums.YesOrNoEnum;
import com.bskj.common.service.impl.BaseServiceImpl;
import com.bskj.common.utils.DateTimeUtil;
import com.bskj.common.utils.EncryptUtil;
import com.bskj.common.utils.HttpClientUtils;
import com.bskj.common.utils.LogUtils;
import com.bskj.common.utils.StringUtils;
import com.bskj.common.utils.XMLUtil;
import com.bskj.kuaifu.service.IUserCouponService;
import com.bskj.kuaifu.service.IUserInfoService;

/**
 * Created by mocaijin on 21/12/2017.
 */
@Service
public class UserCouponServiceImpl extends BaseServiceImpl<UserCoupon> implements IUserCouponService {

	@Autowired
	private UserCouponDao userCouponDao;

	@Autowired
	private ShopCouponDao shopCouponDao;
	
	@Autowired
	private ParkingShopDao parkingShopDao;

	@Autowired
	private ParkingLotCustomerDao parkingLotCustomerDao;
	
	@Autowired
	private ThirdPlatformInterfaceDao thirdPlatformInterfaceDao;
	
	@Autowired
	private IUserInfoService userInfoService;
	
	@Autowired
	private UserCarDao userCarDao;

	@Override
	public BaseDao<UserCoupon> getBaseDao() {
		return userCouponDao;
	}

	@Override
	public List<UserCoupon> find(UserCoupon userCoupon) throws Exception {
		FindRequestEntity findReq = new FindRequestEntity();
		if (userCoupon.getUserId() != null) {
			findReq.addWhere("user_id", WhereEnum.EQ, userCoupon.getUserId());
		}
		if (userCoupon.getStatus() != null) {
			findReq.addWhere("status", WhereEnum.EQ, userCoupon.getStatus());
		}
		if (userCoupon.getStatus() != null) {
			findReq.addWhere("valid_date", WhereEnum.LE, userCoupon.getValidDate());
		}
		return find(findReq);
	}

	@Override
	public List<UserCoupon> findCascade(UserCoupon userCoupon) throws Exception {
		List<UserCoupon> userCouponList = new ArrayList<>();
		FindRequestEntity findReq = new FindRequestEntity();
		findReq.addWhere("user_id", WhereEnum.EQ, userCoupon.getUserId());
		findReq.addWhere("status", WhereEnum.EQ, userCoupon.getStatus());
		if (userCoupon.getExpireDate() != null) {
			findReq.addWhere("valid_date", WhereEnum.LT, userCoupon.getExpireDate());
		}
		if (userCoupon.getValidDate() != null) {
			findReq.addWhere("valid_date", WhereEnum.GT, userCoupon.getValidDate());
		}
		findReq.setPage(1, 10);
		findReq.addOrder("update_time", OrderEnum.DESC);
		userCouponList = userCouponDao.find(findReq);
		for (UserCoupon userCou : userCouponList) {
			userCou.setParkingLotCustomer(parkingLotCustomerDao.get(userCou.getParkingLotCustomerId()));
			userCou.setParkingShop(parkingShopDao.get(userCou.getShopId()));
		}
		return userCouponList;
	}

	public UserCoupon getValidCoupon(Integer parkLotCustomerId, Integer userId, Date outTime) throws Exception {
		FindRequestEntity findReq = new FindRequestEntity();
		findReq.addWhere("parking_lot_customer_id", WhereEnum.EQ, parkLotCustomerId);
		findReq.addWhere("user_id", WhereEnum.EQ, userId);
		findReq.addWhere("valid_date", WhereEnum.GE, outTime);
		findReq.addWhere("status", WhereEnum.EQ, CouponStatusEnum.not_use.getKey());

		
		findReq.addOrder("coupon_money_type", OrderEnum.DESC);
		findReq.addOrder("money", OrderEnum.DESC);
		findReq.setPage(1, 1);

		List<UserCoupon> userCouponList = find(findReq);
		if (userCouponList != null && userCouponList.size() > 0) {
			return userCouponList.get(0);
		}
		return null;
	}

	@Override
	public boolean getCouponLimitMoney(Integer id) throws Exception {
		ShopCoupon shopCoupon = shopCouponDao.get(id);
		if(shopCoupon == null) {
			return false;
		}
		
		if(shopCoupon.getLimitModeType() == null) {
			shopCoupon.setLimitModeType(CouponLimitModeTypeEnum.Time_Number_Type.getKey());
		}
		
		CouponLimitModeTypeEnum couponLimitModeType = CouponLimitModeTypeEnum.get(shopCoupon.getLimitModeType()); 
		if(couponLimitModeType == null) {
			couponLimitModeType = CouponLimitModeTypeEnum.Time_Number_Type;
		}
		
		if(CouponLimitModeTypeEnum.Time_Number_Type.equals(couponLimitModeType)) {
			//时间段限制模式
			String startTime = "";
			String endTime = "";
			Date endDate = new Date();
			if (shopCoupon.getCouponLimitType() == CouponTimeTypeEnum.every_day.getKey()) {
				//每天限制券张数
				Date beginDate = new Date();
				beginDate = DateTimeUtil.string2Date(DateTimeUtil.date2String(new Date(), "yyyy-MM-dd") + " 00:00:00");
				startTime = DateTimeUtil.date2String(beginDate);
				endTime = DateTimeUtil.date2String(endDate);
			} else if (shopCoupon.getCouponLimitType() == CouponTimeTypeEnum.every_week.getKey()) {
				//每周限制券张数
				Calendar cal = Calendar.getInstance();
				cal.setTime(new Date());
				cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
				Date beginDate = cal.getTime();
				startTime = DateTimeUtil.date2String(beginDate, "yyyy-MM-dd 00:00:00");
				endTime = DateTimeUtil.date2String(endDate);
			} else if (shopCoupon.getCouponLimitType() == CouponTimeTypeEnum.every_month.getKey()) {
				//每月限制券张数
				Calendar cal = Calendar.getInstance();
				cal.add(Calendar.MONTH, 0);
				cal.set(Calendar.DAY_OF_MONTH, 1);
				Date beginDate = cal.getTime();
				startTime = DateTimeUtil.date2String(beginDate, "yyyy-MM-dd 00:00:00");
				endTime = DateTimeUtil.date2String(endDate);
			} else if (shopCoupon.getCouponLimitType() == CouponTimeTypeEnum.annually.getKey()) {
				//每年限制券张数
				startTime = DateTimeUtil.date2String(new Date(), "yyyy-01-01 00:00:00");
				endTime = DateTimeUtil.date2String(new Date(), "yyyy-12-31 23:59:59");
			} else {
				return false;
			}
			int usedCount = userCouponDao.getDailyTotal(shopCoupon.getParkingLotCustomerId() + "", startTime, endTime, shopCoupon.getId());
			return shopCoupon.getCouponLimitNum() - usedCount > 0;
		} else if (CouponLimitModeTypeEnum.Inventory_Type.equals(couponLimitModeType)) {
			//库存限制模式
			//TODO 直接使用数据库查询数据当作库存在并发情况下有问题。可以使用redis缓存（原子操作）来做库存管理。。暂不处理
			Integer inventory = shopCoupon.getInventory();
			if (inventory == null) {
				return false;
			}
			return inventory > 0;
		}
		return false;
	}
	
	@Override
	public boolean getCouponStatus(UserCoupon userCoupon) throws Exception {
		FindRequestEntity findReq=new FindRequestEntity();
		if(userCoupon.getShopId() != null){
			findReq.addWhere("shop_id", WhereEnum.EQ, userCoupon.getShopId());
			findReq.addWhere("coupon_id", WhereEnum.EQ, userCoupon.getCouponId());
			findReq.addOrder("create_time", OrderEnum.DESC);
			findReq.setPage(1, 1);
			
			List<UserCoupon> userCoupons=userCouponDao.find(findReq);
			if(userCoupons != null && userCoupons.size()  > 0){
				if(userCoupons.get(0).getUuid().equals(userCoupon.getUuid())){
					return true;
				}
			}
		}
		findReq=new FindRequestEntity();
		if(userCoupon.getUuid() != null){
			findReq.addWhere("uuid", WhereEnum.EQ, userCoupon.getUuid());
			int userCoupons=userCouponDao.count(findReq.getWhereList());
			if(userCoupons == 0){
				return true;
			}
		}
		return false;
	}
	
	@Override
	public Date getValidDate(Integer id) throws Exception {
		ShopCoupon shopCoupon = shopCouponDao.get(id);
		if (shopCoupon.getValidType() == ShopCouponValidTypeEnum.coupon_crtain.getKey()) {
			double time = shopCoupon.getValidTime();
			int hour = (int) time;
			int min = (int) ((time - hour) * 60);
			long ms = hour * 60 * 60 * 1000L + min * 60 * 1000L + System.currentTimeMillis();
			Date date = new Date(ms);
			return date;
		} else {
			if ("24:00".equals(shopCoupon.getLastTime())) {
				String date = DateTimeUtil.date2String(new Date(), "yyyy-MM-dd") + " 23:59:59";
				return DateTimeUtil.string2Date(date);
			} else {
				String date = DateTimeUtil.date2String(new Date(), "yyyy-MM-dd") + " " + shopCoupon.getLastTime()
						+ ":00";
				return DateTimeUtil.string2Date(date);
			}

		}
	}
	
	@Override
	public Map<String, Object> userReceiveCoupon(UserCoupon userCoupon,Integer userId, String carNo) throws Exception {
		Map<String, Object> resultMap = new HashMap<>();
		
		//首先判断车牌是否被人绑定，谁绑定的
		UserInfo userInfo = userInfoService.get(userId);
		FindRequestEntity findCar = new FindRequestEntity();
		findCar.addWhere("appid", WhereEnum.EQ, userInfo.getAppid());
		findCar.addWhere("car_no", WhereEnum.EQ, carNo);
		List<UserCar> userCarList = userCarDao.find(findCar);
		if(userCarList != null && userCarList.size() > 0){
			userId = userCarList.get(0).getUserId();
		}else {
			//找不到就默认把车牌绑定到当前用户下
			UserCar userCar = new UserCar();
			userCar.setUserId(userInfo.getId());
			userCar.setAppid(userInfo.getAppid());
			userCar.setCarNo(carNo);
			userCar.setStatus(0);
			userCar.setCreateTime(new Date());
			userCar.setUpdateTime(new Date());
			userCarDao.insert(userCar);
		}
		
		
		//根据券的扫码规则判断该券能否被领取
		if(userCoupon.getSweepCode() == null) {
			userCoupon.setSweepCode(SweepCodeEnum.Multi_scan.getKey());
		}
		
		if(SweepCodeEnum.One_yard_sweep.equals(SweepCodeEnum.get(userCoupon.getSweepCode()))){
			//一码一扫的需要判断是否被领取了
			if(getCouponNum(userCoupon)){
				resultMap.put("result", false);
				resultMap.put("errorCode", "40001");
				resultMap.put("errorMsg", "该券已经被领取");
				return resultMap;
			}
		}

		//判断券是否已经领取完
		if (!getCouponLimitMoney(userCoupon.getCouponId())) {
			resultMap.put("result", false);
			resultMap.put("errorCode", "40001");
			resultMap.put("errorMsg", "券已经被领取完");
			return resultMap;
		}

		//判断券是否已经过期
		if (!getCouponStatus(userCoupon)) {
			resultMap.put("result", false);
			resultMap.put("errorCode", "40002");
			resultMap.put("errorMsg", "券已经过期");
			return resultMap;
		}

		//领取券
		userCoupon.setValidDate(getValidDate(userCoupon.getCouponId()));
		userCoupon.setUserId(userId);
		userCoupon.setStatus(0);
		userCoupon.setValidDate(getValidDate(userCoupon.getCouponId()));
		userCoupon.setCreateTime(new Date());
		userCoupon.setUpdateTime(new Date());
		insert(userCoupon);
		
		//如果是库存模式，库存减一 
		//TODO 库存管理存在线程问题，应该使用redis来管理。因为是临时方案，理论上也不存在并发问题，暂不处理。。。。
		ShopCoupon shopCoupon = shopCouponDao.get(userCoupon.getCouponId());
		if (shopCoupon != null) {
			CouponLimitModeTypeEnum limitModeType = CouponLimitModeTypeEnum.get(shopCoupon.getLimitModeType());
			if(CouponLimitModeTypeEnum.Inventory_Type.equals(limitModeType)) {
				int originInventory = shopCoupon.getInventory() == null ? 0 : shopCoupon.getInventory();
				shopCoupon.setInventory(originInventory - 1);
				shopCouponDao.update(shopCoupon);
			}
		}
		
		

		//判断该券是否需要推到第三方平台
		Integer parkingLotCustomerId = userCoupon.getParkingLotCustomerId();
		ParkingLotCustomer parkingLotCustomer = parkingLotCustomerDao.get(parkingLotCustomerId);
		if (parkingLotCustomer != null && YesOrNoEnum.Yes.getKey() == parkingLotCustomer.getIsInterfaceToThird()) {
			String thirdPlatform = parkingLotCustomer.getThirdPlatform();
			FindRequestEntity findReq = new FindRequestEntity();
			findReq.addWhere("platform", WhereEnum.EQ, thirdPlatform);
			findReq.addWhere("interface_desc", WhereEnum.EQ, "push_coupon"); //暂时写死
			List<ThirdPlatformInterface> interfaceList = thirdPlatformInterfaceDao.find(findReq);
			if (interfaceList != null && interfaceList.size() > 0) {
				ThirdPlatformInterface pushCouponInterface = interfaceList.get(0);

				String pushCouponUrl = pushCouponInterface.getUrl();

				//TODO 参数暂时按智享云写死。。。以后有时间再去想怎么扩展到通用方法
				String parkNo = parkingLotCustomer.getUuid();
				String pKey = parkingLotCustomer.getSign();// "12ABE2CE"; //车场的PKey 暂时只有一个 写死
				ParkingShop shop = parkingShopDao.get(userCoupon.getShopId());
				String customerID = "";
				if (shop != null) {
					customerID = shop.getPhone();
				}

				
				int need0Nums = 5 - customerID.length() < 0 ? 0 : 5 - customerID.length();
				if (need0Nums > 0) {
					String zeroStr = "";
					for (int i = 0; i < need0Nums; i++) {
						zeroStr += "0";
					}
					customerID = zeroStr + customerID;
				}

				String url = pushCouponUrl
						+ "?ParkNo=%s&OperateType=%s&CarNo=%s&DistType=%s&DistFee=%s&StartTime=%s&EndTime=%s&CustomerID=%s";	

				url = String.format(url, parkNo, "new", carNo, "3", "" + (userCoupon.getMoney() / 10),
						DateTimeUtil.date2String(new Date(), "yyyyMMddHHmmss"),
						DateTimeUtil.date2String(userCoupon.getValidDate(), "yyyyMMddHHmmss"), customerID);
				String token = EncryptUtil.getMD5(url.toLowerCase() + pKey.toLowerCase());
				url = url + "&Token=" + token;
				LogUtils.info("push coupon url ： " + url);
				String respone = HttpClientUtils.doGet(url);
				LogUtils.info("push coupon ： " + respone);
				Map<String,String> pushCouponRespMap = XMLUtil.xml2Map(respone);
				if(!"0000".equals(pushCouponRespMap.get("ErrNo"))) {
					// 如果推送券失败，直接回滚
					String errorMsg = String.format("推送停车券动作失败！响应结果 ：%s! url：%s", respone, url);
					LogUtils.error(errorMsg);
					throw new Exception(errorMsg);
				} else {
					String errorMsg = String.format("推送停车券动作成功！响应结果 ：%s! url：%s", respone, url);
					LogUtils.info(errorMsg);
				}
				
			}
		}

		resultMap.put("result", true);
		resultMap.put("errorCode", "00000");
		resultMap.put("errorMsg", "领取成功");
		return resultMap;
	}
	
	/**
	 * 根据uuid和coupon_id查找是否有人领券 
	 * @param userCoupon
	 * @return 有返回true 没有返回false
	 * @throws Exception
	 */
	private boolean getCouponNum(UserCoupon userCoupon)throws Exception{
		FindRequestEntity findReq = new FindRequestEntity();
		findReq.addWhere("uuid", WhereEnum.EQ, userCoupon.getUuid());
		findReq.addWhere("coupon_id", WhereEnum.EQ, userCoupon.getCouponId());
		List<UserCoupon> userCouponList = userCouponDao.find(findReq);
		if(userCouponList != null && userCouponList.size() > 0){
			return true;
		}
		return false;
	}
}
